package edu.unice.simul.vue;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.List;

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JProgressBar;

import edu.unice.simul.controleur.SimulationControleur;
import edu.unice.simul.events.MobilesMovedEvent;
import edu.unice.simul.listeners.FinalStatsListener;
import edu.unice.simul.listeners.MobilesChangedListener;
import edu.unice.simul.listeners.TimeListener;
import edu.unice.simul.modele.contenus.Contenu;
import edu.unice.simul.util.Dim;
import edu.unice.simul.util.stats.StatsContainer;
import edu.unice.simul.vue.components.simul.TabPanel;
import edu.unice.simul.vue.moteur_graphique.MoteurGraphique;

/**
 * Fenêtre principale de la simulation
 */
public class SimulationFrame extends JFrame implements MobilesChangedListener,
		FinalStatsListener {
	private static final long serialVersionUID = -1154060589757673805L;

	private SimulationControleur controler;
	private List<Contenu> contenu;
	private MoteurGraphique moteurGraphique = null;
	private Dim dimPiece = null;
	private StatsFrame statsFrame = new StatsFrame();

	private TabPanel tabPanel;
	private JDialog dialog = new JDialog(this);
	private JMenuItem mntmNouvelleSimulation = new JMenuItem(
			"Relancer la simulation");

	public SimulationFrame(SimulationControleur controler, List<Contenu> contenu,
			Dim dimPiece) {
		this.controler = controler;
		this.contenu = contenu;
		this.dimPiece = dimPiece;
		buildUI();
		addListeners();
	}

	/**
	 * Ajoute les écouteurs
	 */
	private void addListeners() {
		mntmNouvelleSimulation.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				controler.reset();
			}
		});
	}

	/**
	 * Construit l'interface
	 */
	private void buildUI() {
		setLayout(new BorderLayout());
		setTitle("Simulateur de foules");
		setVisible(true);

		this.moteurGraphique = new MoteurGraphique(this.contenu, this.dimPiece);

		JPanel westPanel = new JPanel();
		westPanel.add(this.moteurGraphique);
		add(westPanel, BorderLayout.WEST);

		JMenuBar menuBar = new JMenuBar();
		setJMenuBar(menuBar);

		JMenu mnMenu = new JMenu("Menu");
		menuBar.add(mnMenu);

		mnMenu.add(mntmNouvelleSimulation);

		tabPanel = new TabPanel(controler, moteurGraphique);
		add(tabPanel, BorderLayout.EAST);

		pack();

		addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				controler.pause();
			}
		});

		dialog.setTitle("Chargement en cours");
		JProgressBar progressBar = new JProgressBar();
		progressBar.setIndeterminate(true);
		progressBar.setString("Chargement en cours...");
		progressBar.setStringPainted(true);
		dialog.add(progressBar);
		dialog.setResizable(false);

		dialog.setPreferredSize(new Dimension(400, 40));
		dialog.pack();
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

		dialog.setLocation((screenSize.width - dialog.getWidth()) / 2,
				(screenSize.height - dialog.getHeight()) / 2);

		setLocation((screenSize.width - getWidth()) / 2,
				(screenSize.height - getHeight()) / 2);
	}

	/**
	 * Méthode appellée lorsque les humains ont étés mis à jour
	 */
	@Override
	public void mobilesChanged(MobilesMovedEvent event) {
		if (moteurGraphique != null)
			moteurGraphique.refresh(event.getMobiles());
	}

	/**
	 * Méthode appellée lorsque le nombre d'humains dans la pièce a été mis à jour
	 */
	@Override
	public void numberOfMobilesChanged(int newNumber) {
		tabPanel.getStatsPanel().setNumberOfMobiles(newNumber);
	}

	public TimeListener getTimeListener() {
		return tabPanel.getStatsPanel().getTimeListener();
	}

	public FinalStatsListener getFinalStatsListener() {
		return this;
	}

	/**
	 * Lance l'affichage du chargement lors du calcul du chemin
	 */
	public void startLoading() {
		dialog.setVisible(true);
	}

	/**
	 * Masque l'affichage du chargement lorsque le calcul du chemin est terminé
	 */
	public void stopLoading() {
		dialog.setVisible(false);
	}

	/**
	 * Transition entre la fenêtre de simulation et l'affichage des statistiques
	 * de fin de simulation
	 */
	@Override
	public void sendFinalStats(StatsContainer stats) {
		tabPanel.freeze();
		statsFrame.showFinalStats(stats);
	}
}
